#include <jni.h>
#include <string>
#include "SimpleNesCore/Famicom.h"

Famicom *nesdevice = nullptr;

extern "C"
JNIEXPORT void JNICALL
Java_cn_dingd_simplenes_SimpleNes_emulationFrame(JNIEnv *env, jobject thiz) {
    nesdevice->EmulationFrame();
}

extern "C"
JNIEXPORT jbyteArray JNICALL
Java_cn_dingd_simplenes_SimpleNes_getCanvas(JNIEnv *env, jobject thiz) {
    unsigned int length = 256 * 240;

    char *buf = (char *) nesdevice->GetCanvas();

    jbyteArray data = env->NewByteArray(length);
    env->SetByteArrayRegion(data, 0, length, (jbyte *) buf);
    env->ReleaseByteArrayElements(data, env->GetByteArrayElements(data, JNI_FALSE), 0);
    return data;
}
extern "C"
JNIEXPORT jshortArray JNICALL
Java_cn_dingd_simplenes_SimpleNes_getSamples(JNIEnv *env, jobject thiz) {
    unsigned int size = 0;
    short *buf = (short *) nesdevice->GetSamples(&size);
    jshortArray data = env->NewShortArray(size);
    env->SetShortArrayRegion(data, 0, size, (jshort *) buf);
    env->ReleaseShortArrayElements(data, env->GetShortArrayElements(data, JNI_FALSE), 0);
    return data;
}
extern "C"
JNIEXPORT void JNICALL
Java_cn_dingd_simplenes_SimpleNes_userinput(JNIEnv *env, jobject thiz, jint index, jint state) {
    // TODO: implement userinput()
    nesdevice->UserInput(index & 0xff, state);
}
extern "C"
JNIEXPORT void JNICALL
Java_cn_dingd_simplenes_SimpleNes_init(JNIEnv *env, jobject thiz) {
    nesdevice = new Famicom();
}

extern "C"
JNIEXPORT jboolean JNICALL
Java_cn_dingd_simplenes_SimpleNes_loadRom(JNIEnv *env, jobject thiz, jbyteArray bytes) {
    jbyte *rombytes = env->GetByteArrayElements(bytes, 0);
    int chars_len = env->GetArrayLength(bytes);
    nesdevice->cartridge->LoadRom((unsigned char *) rombytes, chars_len);
    return true;
}

extern "C"
JNIEXPORT jint JNICALL
Java_cn_dingd_simplenes_SimpleNes_validate(JNIEnv *env, jobject thiz, jbyteArray bytes) {
    jbyte *rombytes = env->GetByteArrayElements(bytes, 0);
    int chars_len = env->GetArrayLength(bytes);
    unsigned int bodysize = 0;
    nesdevice->cartridge->Validate((unsigned char *) rombytes, chars_len, &bodysize);
    return bodysize;
}
extern "C"
JNIEXPORT void JNICALL
Java_cn_dingd_simplenes_SimpleNes_reset(JNIEnv *env, jobject thiz) {
    nesdevice->Reset();
}
extern "C"
JNIEXPORT void JNICALL
Java_cn_dingd_simplenes_SimpleNes_play(JNIEnv *env, jobject thiz) {
    nesdevice->Play();
}
extern "C"
JNIEXPORT void JNICALL
Java_cn_dingd_simplenes_SimpleNes_pause(JNIEnv *env, jobject thiz) {
    nesdevice->Pause();
}